package com.jml.spring.IOC.注解方式.annotation;

import com.jml.spring.IOC.注解方式.annotation.反射工具类.ClassUtil;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.util.StringUtils;

//手写springioc注解版本
public class ExtClassPathXmlApplicationContext {

	private String packageName ;

	//springbean 容器
	private static ConcurrentHashMap<String,Object> beans = null;

	public ExtClassPathXmlApplicationContext(String packageName) throws Exception {
		this.packageName = packageName;
		beans = new ConcurrentHashMap<String,Object>();
		initBean();
		//初始化完毕进行依赖注入
		initEntryField();
	}

	public void initEntryField() throws Exception {
		//遍历所有的bean容器对象
		for(Map.Entry<String,Object> entry: beans.entrySet()){
			//判断属性上是否有注解进行依赖注入
			Object obj = entry.getValue();
			//依赖注入
			attriAssign(obj);
		}
	}

	public Object getBean(String beanId) throws Exception {
		if(StringUtils.isEmpty(beanId)){
			throw new Exception(beanId+"不能为空");
		}
		Object obj = beans.get(beanId);
		return obj;
	}

	//3.使用java的反射机制进行初始化
	private Object newInstance(Class<?> beanClass)throws  Exception {
		return beanClass.newInstance();
	}

	public void initBean() throws Exception {
		//1.根据java反射机制进行扫包，获取当前包下的所有类
		List<Class<?>> classes = ClassUtil.getClasses(packageName);
		//2.判断类上是否存在注入bean的注解
		ConcurrentHashMap<String,Object> classExitsAnnotation =  findClassExistAnnotation(classes);
		if(classExitsAnnotation==null||classExitsAnnotation.size()==0){
			throw  new Exception("该包下没有任何类注解");
		}
	}


	public ConcurrentHashMap<String,Object> findClassExistAnnotation(List<Class<?>> classes)
			throws Exception {
		for (Class<?> classInfo: classes) {
			//判断类上是否有注解
			ExtService extService = classInfo.getAnnotation(ExtService.class);
			if(extService!=null){
				//获取当前类名
				String className = classInfo.getSimpleName();
				//类名首字母小写
				String beanId = toLowerCaseFirstOne(className);
				Object newInstance = newInstance(classInfo);
				beans.put(beanId,newInstance);
			}
		}
		return beans;
	}

	// 首字母转小写
	public static String toLowerCaseFirstOne(String s) {
		if (Character.isLowerCase(s.charAt(0)))
			return s;
		else
			return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
	}

	//依赖注入
	public void attriAssign(Object object) throws Exception {
		//1.使用反射机制获取当前类的所有属性，
		Class<?> classInfo = object.getClass();
		Field[] declaredFields = classInfo.getDeclaredFields();
		//2.判断当前类是否存在注解
		for (Field field:declaredFields) {
			ExtResource extResource = field.getAnnotation(ExtResource.class);
			if(extResource!=null){
				//3.默认使用属性名称查找bean对象
				String beanId = field.getName();
				Object bean = getBean(beanId);
				if(bean!=null){
					//给当前对象object的属性赋值bean
					//运行访问私有属性
					field.setAccessible(true);
					field.set(object,bean);
				}
			}
		}
	}
}
